#pragma once

#include <map>

#define PAN_WINDOW_INFO_FETCHER         _T("atom_window_info_fetcher")

enum {
    PFI_WINDOW_INFO_FETCHER_BASE    = 300,

    // Param = WindowProcInfo, IOParam = bool
    PFI_GET_WINDOW_PROC_INFO,

    // Param = WindowThreadInfo, IOParam = bool
    PFI_GET_WINDOW_THREAD_INFO,

    // Param = WindowInfo, IOParam = bool
    PFI_GET_WINDOW_INFO,

    // Param = WindowProps, IOParam = bool
    PFI_GET_WINDOW_PROPS,

    // Param = CString *, IOParam = CString *
    PFI_GET_WINDOW_PROP,

    // Param = CString *, IOParam = CString *
    PFI_SET_WINDOW_PROP,

    // Param = CString *, IOParam = bool
    PFI_REMOVE_WINDOW_PROP,
};

struct WindowProcInfo {
    DWORD m_dwPid;
    CString m_strProcName;

    WindowProcInfo() : m_dwPid(0) {}
};

struct WindowThreadInfo {
    DWORD m_dwTid;
    CString m_strThreadName;
    HWND m_hFocusWindow;
    CString m_strFocusWindowName;
    HWND m_hActiveWindow;
    CString m_strActiveWindowName;
    HWND m_hCaptureWindow;
    CString m_strCaptureWindowName;
    HWND m_hForegroundWindow;
    CString m_strForegroundWindowName;

    WindowThreadInfo()
        : m_dwTid(0)
        , m_hFocusWindow(NULL)
        , m_hActiveWindow(NULL)
        , m_hCaptureWindow(NULL)
        , m_hForegroundWindow(NULL)
    {}
};

struct WindowInfo {
    LONG m_nStyle;
    LONG m_nExStyle;
    HWND m_hParent;
    CString m_strParentName;
    HWND m_hOwner;
    CString m_strOwnerName;
    RECT m_oWindowRect;
    RECT m_oClientRect;

    WindowInfo()
        : m_nStyle(0)
        , m_nExStyle(0)
        , m_hParent(NULL)
        , m_hOwner(NULL)
    {
        memset(&m_oWindowRect, 0, sizeof(RECT));
        memset(&m_oClientRect, 0, sizeof(RECT));
    }
};

struct WindowPropKey {
    CString m_strPropKey;
    bool m_bIsAtom;

    WindowPropKey() : m_bIsAtom(false) {}

    bool operator < (const WindowPropKey &rhs) const {
        if(m_bIsAtom == rhs.m_bIsAtom) {
            return m_strPropKey < rhs.m_strPropKey;
        }

        return m_bIsAtom < rhs.m_bIsAtom;
    }

    bool operator == (const WindowPropKey &rhs) const {
        return (m_bIsAtom == rhs.m_bIsAtom) && (m_strPropKey == rhs.m_strPropKey);
    }
};

struct WindowProps {
    std::map<WindowPropKey, HANDLE> m_vPropList;
};